package com.donar.concurrent.lock;

import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.LockSupport;

/**
 阻塞锁的优势在于，阻塞的线程不会占用cpu时间， 不会导致 CPu占用率过高，但进入时间以及恢复时间都要比自旋锁略慢。

 在竞争激烈的情况下 阻塞锁的性能要明显高于 自旋锁。

 理想的情况则是; 在线程竞争不激烈的情况下，使用自旋锁，竞争激烈的情况下使用，阻塞锁。
 */
public class BlockLock {
    public static  class  CLHNode{
        private volatile Thread isLocked;
    }
    private CLHNode tail;
    private static final ThreadLocal<CLHNode> LOCAL = new ThreadLocal<CLHNode>();
    private static final AtomicReferenceFieldUpdater<BlockLock,CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(BlockLock.class,CLHNode.class,"tail");

    public void lock(){
        CLHNode node = new CLHNode();
        LOCAL.set(node);
        //Thread1 进来 执行到这里 得到的preNode为空 此时tail 已经设置为node1了 || Thread2 进来时preNode 等于 node1 tail = node2
        CLHNode preNode = UPDATER.getAndSet(this,node);
        if(preNode!=null){
            //Thread2 请求获取node1的锁
            preNode.isLocked = Thread.currentThread();
            //等待Thread2 解锁
            LockSupport.park(this);
            preNode = null;
            LOCAL.set(node);
        }
    }


    public void unlock(){
        //Thread1 调用unlock 获取node1
        CLHNode node = LOCAL.get();
        //此时tail 已经 node2
        if(!UPDATER.compareAndSet(this,node,null)){
            //解锁node1的线程
            LockSupport.unpark(node.isLocked);
        }
        node = null;
    }

}
